"""
推理引擎

这个模块实现了 Agent 的推理能力，展示了 AI Agent 如何：
1. 分析问题和上下文
2. 制定解决策略
3. 选择合适的工具
4. 进行逻辑推理
5. 评估解决方案的可行性

推理引擎是 Agent 智能行为的核心组件。
"""

import json
import asyncio
from typing import List, Dict, Any, Optional
from dataclasses import dataclass
from enum import Enum

try:
    import openai
except ImportError:
    openai = None


class ActionType(Enum):
    """行动类型枚举"""
    DIRECT_ANSWER = "direct_answer"
    TOOL_CALL = "tool_call" 
    PLAN_TASK = "plan_task"
    SEARCH_MEMORY = "search_memory"
    ASK_CLARIFICATION = "ask_clarification"


@dataclass
class ReasoningStep:
    """推理步骤"""
    thought: str                              # 思考内容
    action_type: Optional[ActionType] = None  # 行动类型
    action_data: Optional[Dict] = None        # 行动数据
    confidence_score: Optional[float] = None  # 信心指数 (0-10)
    rationale: Optional[str] = None           # 推理依据


@dataclass
class ReasoningResult:
    """推理结果"""
    steps: List[ReasoningStep]                # 推理步骤列表
    final_strategy: str                       # 最终策略
    confidence: float                         # 整体信心指数
    complexity: int                           # 任务复杂度 (1-5)


class ReasoningEngine:
    """
    推理引擎类
    
    负责分析用户问题，制定解决策略，并提供详细的推理过程。
    这展示了 AI Agent 如何进行"思考"的过程。
    """
    
    def __init__(self):
        self.client = None
        self._init_client()
    
    def _init_client(self):
        """初始化 AI 客户端"""
        import os
        api_key = os.getenv("OPENAI_API_KEY")
        if api_key and openai:
            try:
                self.client = openai.OpenAI(api_key=api_key)
            except:
                self.client = None
        else:
            self.client = None
    
    async def analyze(
        self, 
        user_input: str, 
        conversation_history: List[Dict],
        relevant_memories: List[Any],
        available_tools: List[str]
    ) -> ReasoningResult:
        """
        分析用户输入并生成推理结果
        
        这是推理引擎的核心方法，展示了完整的分析过程：
        1. 理解用户意图
        2. 分析上下文信息
        3. 评估可用资源
        4. 制定解决策略
        5. 计算信心指数
        """
        
        # 1. 基础分析
        intent_analysis = self._analyze_intent(user_input)
        context_analysis = self._analyze_context(conversation_history, relevant_memories)
        
        # 2. 生成推理步骤
        steps = []
        
        # 步骤1：理解问题
        steps.append(ReasoningStep(
            thought=f"用户询问: '{user_input}' - 意图分析: {intent_analysis['intent']}",
            confidence_score=intent_analysis['confidence']
        ))
        
        # 步骤2：评估上下文
        if context_analysis['has_relevant_context']:
            steps.append(ReasoningStep(
                thought=f"发现相关上下文: {context_analysis['summary']}",
                confidence_score=8.0
            ))
        
        # 步骤3：工具选择
        tool_analysis = self._analyze_tool_requirements(user_input, available_tools)
        if tool_analysis['needs_tools']:
            steps.append(ReasoningStep(
                thought=f"需要使用工具: {', '.join(tool_analysis['recommended_tools'])}",
                action_type=ActionType.TOOL_CALL,
                action_data={
                    "tool": tool_analysis['recommended_tools'][0] if tool_analysis['recommended_tools'] else None,
                    "args": tool_analysis['suggested_args']
                },
                confidence_score=tool_analysis['confidence']
            ))
        
        # 步骤4：复杂度评估
        complexity = self._assess_complexity(user_input, intent_analysis, tool_analysis)
        steps.append(ReasoningStep(
            thought=f"任务复杂度评估: {complexity}/5 - {'简单' if complexity <= 2 else '中等' if complexity <= 3 else '复杂'}",
            confidence_score=9.0
        ))
        
        # 步骤5：策略制定
        strategy = self._formulate_strategy(intent_analysis, tool_analysis, complexity)
        steps.append(ReasoningStep(
            thought=f"解决策略: {strategy}",
            action_type=self._determine_action_type(intent_analysis, tool_analysis),
            confidence_score=8.0
        ))
        
        # 计算整体信心指数
        overall_confidence = sum(step.confidence_score or 0 for step in steps) / len(steps)
        
        return ReasoningResult(
            steps=steps,
            final_strategy=strategy,
            confidence=overall_confidence,
            complexity=complexity
        )
    
    def _analyze_intent(self, user_input: str) -> Dict[str, Any]:
        """分析用户意图"""
        # 简化版意图分析 - 实际项目中可以使用更复杂的 NLP 模型
        user_input_lower = user_input.lower()
        
        # 常见意图模式
        intent_patterns = {
            "calculation": ["计算", "算", "数学", "数字", "+", "-", "*", "/"],
            "search": ["搜索", "查找", "找", "search", "find"],
            "file_operation": ["文件", "保存", "读取", "写入", "file"],
            "weather": ["天气", "温度", "weather", "气温", "阴天", "晴天", "下雨"],
            "question": ["什么", "如何", "为什么", "怎么", "?", "？"],
            "task": ["帮我", "请", "任务", "做", "执行"],
            "greeting": ["你好", "hello", "hi", "嗨"],
        }
        
        detected_intents = []
        for intent, keywords in intent_patterns.items():
            if any(keyword in user_input_lower for keyword in keywords):
                detected_intents.append(intent)
        
        primary_intent = detected_intents[0] if detected_intents else "general"
        confidence = 9.0 if detected_intents else 6.0
        
        return {
            "intent": primary_intent,
            "all_intents": detected_intents,
            "confidence": confidence,
            "keywords": [kw for kw in intent_patterns.get(primary_intent, []) 
                        if kw in user_input_lower]
        }
    
    def _analyze_context(self, conversation_history: List[Dict], relevant_memories: List[Any]) -> Dict[str, Any]:
        """分析上下文信息"""
        has_relevant_context = len(conversation_history) > 1 or len(relevant_memories) > 0
        
        context_summary = []
        if conversation_history:
            recent_topics = [msg.get("content", "")[:50] for msg in conversation_history[-3:]]
            context_summary.append(f"最近讨论: {', '.join(recent_topics)}")
        
        if relevant_memories:
            context_summary.append(f"相关记忆: {len(relevant_memories)} 条")
        
        return {
            "has_relevant_context": has_relevant_context,
            "summary": " | ".join(context_summary) if context_summary else "无相关上下文",
            "conversation_length": len(conversation_history),
            "memory_count": len(relevant_memories)
        }
    
    def _analyze_tool_requirements(self, user_input: str, available_tools: List[str]) -> Dict[str, Any]:
        """分析工具需求"""
        user_input_lower = user_input.lower()
        
        # 工具需求模式
        tool_patterns = {
            "calculator": ["计算", "算", "数学", "+", "-", "*", "/", "数字"],
            "search": ["搜索", "查找", "找", "search"],
            "filesystem": ["文件", "保存", "读取", "写入", "创建"],
            "weather": ["天气", "温度", "weather", "气温", "阴天", "晴天", "下雨"],
            "time": ["时间", "日期", "现在几点", "today"]
        }
        
        recommended_tools = []
        suggested_args = {}
        
        for tool, keywords in tool_patterns.items():
            if tool in available_tools and any(keyword in user_input_lower for keyword in keywords):
                recommended_tools.append(tool)
                
                # 为特定工具生成建议参数
                if tool == "calculator":
                    # 提取可能的数学表达式
                    import re
                    math_expr = re.findall(r'[\d+\-*/().\s]+', user_input)
                    if math_expr:
                        suggested_args["expression"] = math_expr[0].strip()
                elif tool == "search":
                    # 提取搜索关键词
                    search_terms = user_input.replace("搜索", "").replace("查找", "").strip()
                    suggested_args["query"] = search_terms
                elif tool == "weather":
                    # 提取城市名称
                    import re
                    # 尝试提取城市名称
                    city_patterns = [
                        r'(北京|上海|广州|深圳|成都|西安|武汉|天津|南京|杭州|苏州|重庆|青岛|大连|宁波|无锡|合肥|福州|厦门|济南|石家庄|郑州|太原|长沙|南昌|昆明|乌鲁木齐|兰州|银川|西宁|呼和浩特|哈尔滨|长春|沈阳)',
                        r'([\u4e00-\u9fa5]+市?)',  # 中文地名
                        r'([A-Za-z\s]+)'  # 英文地名
                    ]
                    
                    city = None
                    for pattern in city_patterns:
                        matches = re.findall(pattern, user_input)
                        if matches:
                            city = matches[0].strip()
                            break
                    
                    if not city:
                        # 如果没有提取到城市，使用默认值
                        city = "北京"
                    
                    suggested_args["city"] = city
                elif tool == "filesystem":
                    # 为文件系统工具提取参数
                    # 默认操作是读取文件
                    suggested_args["operation"] = "read"
                    suggested_args["file_path"] = "./README.md"  # 默认文件路径
        
        needs_tools = len(recommended_tools) > 0
        confidence = 8.0 if needs_tools else 3.0
        
        return {
            "needs_tools": needs_tools,
            "recommended_tools": recommended_tools,
            "suggested_args": suggested_args,
            "confidence": confidence
        }
    
    def _assess_complexity(self, user_input: str, intent_analysis: Dict, tool_analysis: Dict) -> int:
        """评估任务复杂度 (1-5)"""
        complexity = 1
        
        # 基于文本长度
        if len(user_input) > 100:
            complexity += 1
        
        # 基于意图数量
        if len(intent_analysis.get("all_intents", [])) > 1:
            complexity += 1
        
        # 基于工具需求
        if tool_analysis.get("needs_tools", False):
            complexity += 1
            if len(tool_analysis.get("recommended_tools", [])) > 1:
                complexity += 1
        
        # 基于特定模式
        complex_patterns = ["分析", "解释", "比较", "规划", "设计", "优化"]
        if any(pattern in user_input for pattern in complex_patterns):
            complexity += 1
        
        return min(complexity, 5)
    
    def _formulate_strategy(self, intent_analysis: Dict, tool_analysis: Dict, complexity: int) -> str:
        """制定解决策略"""
        strategy_parts = []
        
        intent = intent_analysis.get("intent", "general")
        
        if intent == "calculation" and tool_analysis.get("needs_tools"):
            strategy_parts.append("使用计算器工具进行数学运算")
        elif intent == "search":
            strategy_parts.append("执行搜索操作获取相关信息")
        elif intent == "weather" and tool_analysis.get("needs_tools"):
            strategy_parts.append("使用天气工具查询天气信息")
        elif intent == "question":
            strategy_parts.append("基于知识库提供详细解答")
        elif intent == "task":
            if complexity > 3:
                strategy_parts.append("将复杂任务分解为多个步骤")
            strategy_parts.append("执行相应的操作和工具调用")
        else:
            strategy_parts.append("提供直接回答或引导用户")
        
        if complexity > 2:
            strategy_parts.append("监控执行过程并提供详细反馈")
        
        return " → ".join(strategy_parts)
    
    def _determine_action_type(self, intent_analysis: Dict, tool_analysis: Dict) -> ActionType:
        """确定行动类型"""
        if tool_analysis.get("needs_tools", False):
            return ActionType.TOOL_CALL
        
        intent = intent_analysis.get("intent", "general")
        
        if intent in ["question", "greeting"]:
            return ActionType.DIRECT_ANSWER
        elif intent == "task":
            return ActionType.PLAN_TASK
        else:
            return ActionType.DIRECT_ANSWER
    
    async def explain_reasoning(self, reasoning_result: ReasoningResult) -> str:
        """
        生成推理过程的自然语言解释
        
        这个方法将推理步骤转换为易于理解的解释，
        帮助用户了解 Agent 的思考过程。
        """
        explanation = f"""
## 🧠 Agent 的思考过程

**任务复杂度**: {reasoning_result.complexity}/5
**整体信心**: {reasoning_result.confidence:.1f}/10

### 推理步骤:
"""
        
        for i, step in enumerate(reasoning_result.steps, 1):
            explanation += f"\n**步骤 {i}**: {step.thought}"
            if step.confidence_score:
                explanation += f" (信心度: {step.confidence_score:.1f}/10)"
            
            if step.action_type and step.action_type != ActionType.DIRECT_ANSWER:
                explanation += f"\n  - 计划行动: {step.action_type.value}"
        
        explanation += f"\n\n**最终策略**: {reasoning_result.final_strategy}"
        
        return explanation